from datetime import datetime, timedelta
from typing import Optional, Dict, Any
from jose import JWTError, jwt
from passlib.context import CryptContext
from sqlalchemy.orm import Session
from app.models.user import User, UserProfile
from app.config.settings import settings
import logging

# 配置日志
logger = logging.getLogger(__name__)

# 密码加密上下文
pwd_context = CryptContext(schemes=["bcrypt"], deprecated="auto")

class AuthService:
    """认证服务类"""
    
    def __init__(self):
        self.secret_key = settings.secret_key
        self.algorithm = settings.algorithm
        self.access_token_expire_minutes = settings.access_token_expire_minutes
    
    def verify_password(self, plain_password: str, hashed_password: str) -> bool:
        """验证密码
        
        Args:
            plain_password: 明文密码
            hashed_password: 加密密码
            
        Returns:
            bool: 密码是否正确
        """
        return pwd_context.verify(plain_password, hashed_password)
    
    def get_password_hash(self, password: str) -> str:
        """获取密码哈希值
        
        Args:
            password: 明文密码
            
        Returns:
            str: 加密后的密码
        """
        return pwd_context.hash(password)
    
    def create_access_token(self, data: Dict[str, Any], expires_delta: Optional[timedelta] = None) -> str:
        """创建访问令牌
        
        Args:
            data: 要编码的数据
            expires_delta: 过期时间增量
            
        Returns:
            str: JWT令牌
        """
        to_encode = data.copy()
        
        if expires_delta:
            expire = datetime.utcnow() + expires_delta
        else:
            expire = datetime.utcnow() + timedelta(minutes=self.access_token_expire_minutes)
        
        to_encode.update({"exp": expire})
        encoded_jwt = jwt.encode(to_encode, self.secret_key, algorithm=self.algorithm)
        
        return encoded_jwt
    
    def verify_token(self, token: str) -> Optional[Dict[str, Any]]:
        """验证令牌
        
        Args:
            token: JWT令牌
            
        Returns:
            Optional[Dict[str, Any]]: 解码后的数据，验证失败返回None
        """
        try:
            payload = jwt.decode(token, self.secret_key, algorithms=[self.algorithm])
            return payload
        except JWTError as e:
            logger.error(f"JWT验证失败: {e}")
            return None
    
    def authenticate_user(self, db: Session, username: str, password: str) -> Optional[User]:
        """用户认证
        
        Args:
            db: 数据库会话
            username: 用户名
            password: 密码
            
        Returns:
            Optional[User]: 认证成功返回用户对象，失败返回None
        """
        try:
            # 查找用户（支持用户名或邮箱登录）
            user = db.query(User).filter(
                (User.username == username) | (User.email == username)
            ).first()
            
            if not user:
                logger.warning(f"用户不存在: {username}")
                return None
            
            if not user.is_active:
                logger.warning(f"用户已被禁用: {username}")
                return None
            
            if not self.verify_password(password, user.hashed_password):
                logger.warning(f"密码错误: {username}")
                return None
            
            # 更新最后登录时间
            user.update_last_login()
            db.commit()
            
            logger.info(f"用户认证成功: {username}")
            return user
            
        except Exception as e:
            logger.error(f"用户认证异常: {e}")
            db.rollback()
            return None
    
    def register_user(self, db: Session, username: str, email: str, password: str) -> Dict[str, Any]:
        """用户注册
        
        Args:
            db: 数据库会话
            username: 用户名
            email: 邮箱
            password: 密码
            
        Returns:
            Dict[str, Any]: 注册结果
        """
        try:
            # 检查用户名是否已存在
            existing_user = db.query(User).filter(User.username == username).first()
            if existing_user:
                return {
                    "success": False,
                    "message": "用户名已存在"
                }
            
            # 检查邮箱是否已存在
            existing_email = db.query(User).filter(User.email == email).first()
            if existing_email:
                return {
                    "success": False,
                    "message": "邮箱已被注册"
                }
            
            # 创建新用户
            hashed_password = self.get_password_hash(password)
            new_user = User(
                username=username,
                email=email,
                hashed_password=hashed_password,
                nickname=username,  # 默认昵称为用户名
                is_active=True,
                is_verified=False
            )
            
            db.add(new_user)
            db.flush()  # 获取用户ID
            
            # 创建用户画像
            user_profile = UserProfile(
                user_id=new_user.id,
                favorite_genres={},
                emotional_preferences={},
                viewing_history=[],
                rating_history=[],
                search_history=[]
            )
            
            db.add(user_profile)
            db.commit()
            
            logger.info(f"用户注册成功: {username}")
            
            return {
                "success": True,
                "message": "注册成功",
                "user": new_user.to_dict()
            }
            
        except Exception as e:
            logger.error(f"用户注册异常: {e}")
            db.rollback()
            return {
                "success": False,
                "message": "注册失败，请稍后重试"
            }
    
    def get_user_by_id(self, db: Session, user_id: int) -> Optional[User]:
        """根据ID获取用户
        
        Args:
            db: 数据库会话
            user_id: 用户ID
            
        Returns:
            Optional[User]: 用户对象
        """
        try:
            user = db.query(User).filter(User.id == user_id, User.is_active == True).first()
            return user
        except Exception as e:
            logger.error(f"获取用户异常: {e}")
            return None
    
    def get_user_by_username(self, db: Session, username: str) -> Optional[User]:
        """根据用户名获取用户
        
        Args:
            db: 数据库会话
            username: 用户名
            
        Returns:
            Optional[User]: 用户对象
        """
        try:
            user = db.query(User).filter(
                User.username == username,
                User.is_active == True
            ).first()
            return user
        except Exception as e:
            logger.error(f"获取用户异常: {e}")
            return None
    
    def update_user_profile(self, db: Session, user_id: int, profile_data: Dict[str, Any]) -> Dict[str, Any]:
        """更新用户资料
        
        Args:
            db: 数据库会话
            user_id: 用户ID
            profile_data: 资料数据
            
        Returns:
            Dict[str, Any]: 更新结果
        """
        try:
            user = self.get_user_by_id(db, user_id)
            if not user:
                return {
                    "success": False,
                    "message": "用户不存在"
                }
            
            # 更新允许的字段
            allowed_fields = ['nickname', 'bio', 'avatar_url']
            for field in allowed_fields:
                if field in profile_data:
                    setattr(user, field, profile_data[field])
            
            # 更新偏好设置
            if 'preferences' in profile_data:
                user.set_preferences(profile_data['preferences'])
            
            db.commit()
            
            logger.info(f"用户资料更新成功: {user_id}")
            
            return {
                "success": True,
                "message": "资料更新成功",
                "user": user.to_dict()
            }
            
        except Exception as e:
            logger.error(f"更新用户资料异常: {e}")
            db.rollback()
            return {
                "success": False,
                "message": "更新失败，请稍后重试"
            }
    
    def change_password(self, db: Session, user_id: int, old_password: str, new_password: str) -> Dict[str, Any]:
        """修改密码
        
        Args:
            db: 数据库会话
            user_id: 用户ID
            old_password: 旧密码
            new_password: 新密码
            
        Returns:
            Dict[str, Any]: 修改结果
        """
        try:
            user = self.get_user_by_id(db, user_id)
            if not user:
                return {
                    "success": False,
                    "message": "用户不存在"
                }
            
            # 验证旧密码
            if not self.verify_password(old_password, user.hashed_password):
                return {
                    "success": False,
                    "message": "原密码错误"
                }
            
            # 更新密码
            user.hashed_password = self.get_password_hash(new_password)
            db.commit()
            
            logger.info(f"用户密码修改成功: {user_id}")
            
            return {
                "success": True,
                "message": "密码修改成功"
            }
            
        except Exception as e:
            logger.error(f"修改密码异常: {e}")
            db.rollback()
            return {
                "success": False,
                "message": "修改失败，请稍后重试"
            }
    
    def get_user_profile_data(self, db: Session, user_id: int) -> Dict[str, Any]:
        """获取用户画像数据
        
        Args:
            db: 数据库会话
            user_id: 用户ID
            
        Returns:
            Dict[str, Any]: 用户画像数据
        """
        try:
            user_profile = db.query(UserProfile).filter(UserProfile.user_id == user_id).first()
            if not user_profile:
                # 如果用户画像不存在，创建一个默认的
                user_profile = UserProfile(
                    user_id=user_id,
                    age_group=None,
                    gender=None,
                    location=None,
                    favorite_genres=[],
                    emotional_preferences=[],
                    viewing_history=[],
                    rating_history=[],
                    search_history=[]
                )
                db.add(user_profile)
                db.commit()
                logger.info(f"为用户 {user_id} 创建默认画像")
            
            return {
                "success": True,
                "data": {
                    "age_group": user_profile.age_group,
                    "gender": user_profile.gender,
                    "location": user_profile.location,
                    "favorite_genres": user_profile.favorite_genres or [],
                    "emotional_preferences": user_profile.emotional_preferences or [],
                    "favorite_actors": user_profile.favorite_actors or [],
                    "favorite_directors": user_profile.favorite_directors or [],
                    "mood_history": user_profile.mood_history or []
                }
            }
            
        except Exception as e:
            logger.error(f"获取用户画像异常: {e}")
            return {
                "success": False,
                "message": "获取失败，请稍后重试"
            }
    
    def update_user_profile_data(self, db: Session, user_id: int, profile_data: Dict[str, Any]) -> Dict[str, Any]:
        """更新用户画像数据
        
        Args:
            db: 数据库会话
            user_id: 用户ID
            profile_data: 画像数据
            
        Returns:
            Dict[str, Any]: 更新结果
        """
        try:
            user_profile = db.query(UserProfile).filter(UserProfile.user_id == user_id).first()
            if not user_profile:
                # 如果用户画像不存在，创建一个新的
                user_profile = UserProfile(
                    user_id=user_id,
                    age_group=None,
                    gender=None,
                    location=None,
                    favorite_genres=[],
                    emotional_preferences=[],
                    viewing_history=[],
                    rating_history=[],
                    search_history=[]
                )
                db.add(user_profile)
                logger.info(f"为用户 {user_id} 创建新的画像记录")
            
            # 更新允许的字段
            allowed_fields = ['age_group', 'gender', 'location', 'favorite_genres', 'emotional_preferences', 'favorite_actors', 'favorite_directors', 'mood_history']
            for field in allowed_fields:
                if field in profile_data:
                    setattr(user_profile, field, profile_data[field])
            
            db.commit()
            
            logger.info(f"用户画像更新成功: {user_id}")
            
            return {
                "success": True,
                "message": "画像更新成功",
                "data": {
                    "age_group": user_profile.age_group,
                    "gender": user_profile.gender,
                    "location": user_profile.location,
                    "favorite_genres": user_profile.favorite_genres or [],
                    "emotional_preferences": user_profile.emotional_preferences or [],
                    "favorite_actors": user_profile.favorite_actors or [],
                    "favorite_directors": user_profile.favorite_directors or [],
                    "mood_history": user_profile.mood_history or []
                }
            }
            
        except Exception as e:
            logger.error(f"更新用户画像异常: {e}")
            db.rollback()
            return {
                "success": False,
                "message": "更新失败，请稍后重试"
            }

# 创建认证服务实例
auth_service = AuthService()